globalDefQueue = [];

function isFunction(it) {
    return Object.prototype.toString.call(it) === '[object Function]';
}

function isArray (arr) {
    return Object.prototype.toString.call(arr) === '[object Array]';
}

define = function (name, deps, callback) {
    var node, context;

    //Allow for anonymous modules
    if (typeof name !== 'string') {
        //Adjust args appropriately
        callback = deps;
        deps = name;
        name = null;
    }

    //This module may not have dependencies
    if (!isArray(deps)) {
        callback = deps;
        deps = null;
    }

    //If no name, and callback is a function, then figure out if it a
    //CommonJS thing with dependencies.
    if (!deps && isFunction(callback)) {
        deps = [];
        //Remove comments from the callback string,
        //look for require calls, and pull them into the dependencies,
        //but only if there are function args.
        if (callback.length) {
            callback
                .toString()
                .replace(commentRegExp, commentReplace)
                .replace(cjsRequireRegExp, function (match, dep) {
                    deps.push(dep);
                });

            //May be a CommonJS thing even without require calls, but still
            //could use exports, and module. Avoid doing exports and module
            //work though if it just needs require.
            //REQUIRES the function to expect the CommonJS variables in the
            //order listed below.
            deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
        }
    }


    //Always save off evaluating the def call until the script onload handler.
    //This allows multiple modules to be in a file without prematurely
    //tracing dependencies, and allows for anonymous module support,
    //where the module name is not known until the script onload event
    //occurs. If no context, use the global queue, and get it processed
    //in the onscript load callback.
    if (context) {
        context.defQueue.push([name, deps, callback]);
        context.defQueueMap[name] = true;
    } else {
        globalDefQueue.push([name, deps, callback]);
    }
};


var Fast = {
    config: {
        //toastr默认配置
        toastr: {
            "closeButton": true,
            "debug": false,
            "newestOnTop": false,
            "progressBar": false,
            "positionClass": "toast-top-center",
            "preventDuplicates": false,
            "onclick": null,
            "showDuration": "300",
            "hideDuration": "1000",
            "timeOut": "5000",
            "extendedTimeOut": "1000",
            "showEasing": "swing",
            "hideEasing": "linear",
            "showMethod": "fadeIn",
            "hideMethod": "fadeOut"
        }
    },
    events: {
        //请求成功的回调
        onAjaxSuccess: function (ret, onAjaxSuccess) {
            var data = typeof ret.data !== 'undefined' ? ret.data : null;
            var msg = typeof ret.msg !== 'undefined' && ret.msg ? ret.msg : __('Operation completed');

            if (typeof onAjaxSuccess === 'function') {
                var result = onAjaxSuccess.call(this, data, ret);
                if (result === false)
                    return;
            }
            Toastr.success(msg);
        },
        //请求错误的回调
        onAjaxError: function (ret, onAjaxError) {
            var data = typeof ret.data !== 'undefined' ? ret.data : null;
            if (typeof onAjaxError === 'function') {
                var result = onAjaxError.call(this, data, ret);
                if (result === false) {
                    return;
                }
            }
            Toastr.error(ret.msg);
        },
        //服务器响应数据后
        onAjaxResponse: function (response) {
            try {
                var ret = typeof response === 'object' ? response : JSON.parse(response);
                if (!ret.hasOwnProperty('code')) {
                    $.extend(ret, {code: -2, msg: response, data: null});
                }
            } catch (e) {
                var ret = {code: -1, msg: e.message, data: null};
            }
            return ret;
        }
    },
    api: {
        //发送Ajax请求
        ajax: function (options, success, error) {
            options = typeof options === 'string' ? {url: options} : options;
            var index;
            if (typeof options.loading === 'undefined' || options.loading) {
                index = Layer.load(options.loading || 0);
            }
            options = $.extend({
                type: "POST",
                dataType: "json",
                xhrFields: {
                    withCredentials: true
                },
                success: function (ret) {
                    index && Layer.close(index);
                    ret = Fast.events.onAjaxResponse(ret);
                    if (ret.code === 1) {
                        Fast.events.onAjaxSuccess(ret, success);
                    } else {
                        Fast.events.onAjaxError(ret, error);
                    }
                },
                error: function (xhr) {
                    index && Layer.close(index);
                    var ret = {code: xhr.status, msg: xhr.statusText, data: null};
                    Fast.events.onAjaxError(ret, error);
                }
            }, options);
            return $.ajax(options);
        },
        //修复URL
        fixurl: function (url) {
            if (url.substr(0, 1) !== "/") {
                var r = new RegExp('^(?:[a-z]+:)?//', 'i');
                if (!r.test(url)) {
                    url = Config.moduleurl + "/" + url;
                }
            } else if (url.substr(0, 8) === "/addons/") {
                url = Config.__PUBLIC__.replace(/(\/*$)/g, "") + url;
            }
            return url;
        },
        //获取修复后可访问的cdn链接
        cdnurl: function (url, domain) {
            var rule = new RegExp("^((?:[a-z]+:)?\\/\\/|data:image\\/)", "i");
            var cdnurl = Config.upload.cdnurl;
            url = rule.test(url) || (cdnurl && url.indexOf(cdnurl) === 0) ? url : cdnurl + url;
            if (domain && !rule.test(url)) {
                domain = typeof domain === 'string' ? domain : location.origin;
                url = domain + url;
            }
            return url;
        },
        //查询Url参数
        query: function (name, url) {
            if (!url) {
                url = window.location.href;
            }
            name = name.replace(/[\[\]]/g, "\\$&");
            var regex = new RegExp("[?&/]" + name + "([=/]([^&#/?]*)|&|#|$)"),
                results = regex.exec(url);
            if (!results)
                return null;
            if (!results[2])
                return '';
            return decodeURIComponent(results[2].replace(/\+/g, " "));
        },
        success: function (options, callback) {
            var type = typeof options === 'function';
            if (type) {
                callback = options;
            }
            return Layer.msg(__('Operation completed'), $.extend({
                offset: 0, icon: 1
            }, type ? {} : options), callback);
        },
        error: function (options, callback) {
            var type = typeof options === 'function';
            if (type) {
                callback = options;
            }
            return Layer.msg(__('Operation failed'), $.extend({
                offset: 0, icon: 2
            }, type ? {} : options), callback);
        },
        msg: function (message, url) {
            var callback = typeof url === 'function' ? url : function () {
                if (typeof url !== 'undefined' && url) {
                    location.href = url;
                }
            };
            Layer.msg(message, {
                time: 2000
            }, callback);
        }
    },
    lang: function () {
        var args = arguments,
            string = args[0],
            i = 1;
        string = string.toLowerCase();
        //string = typeof Lang[string] != 'undefined' ? Lang[string] : string;
        if (typeof Lang !== 'undefined' && typeof Lang[string] !== 'undefined') {
            if (typeof Lang[string] == 'object')
                return Lang[string];
            string = Lang[string];
        } else if (string.indexOf('.') !== -1 && false) {
            var arr = string.split('.');
            var current = Lang[arr[0]];
            for (var i = 1; i < arr.length; i++) {
                current = typeof current[arr[i]] != 'undefined' ? current[arr[i]] : '';
                if (typeof current != 'object')
                    break;
            }
            if (typeof current == 'object')
                return current;
            string = current;
        } else {
            string = args[0];
        }
        return string.replace(/%((%)|s|d)/g, function (m) {
            // m is the matched format, e.g. %s, %d
            var val = null;
            if (m[2]) {
                val = m[2];
            } else {
                val = args[i];
                // A switch statement so that the formatter can be extended. Default is %s
                switch (m) {
                    case '%d':
                        val = parseFloat(val);
                        if (isNaN(val)) {
                            val = 0;
                        }
                        break;
                }
                i++;
            }
            return val;
        });
    },
    init: function () {
        // 对相对地址进行处理
        $.ajaxSetup({
            beforeSend: function (xhr, setting) {
                setting.url = Fast.api.fixurl(setting.url);
            }
        });
        // 绑定ESC关闭窗口事件
        $(window).keyup(function (e) {
            if (e.keyCode == 27) {
                if ($(".layui-layer").size() > 0) {
                    var index = 0;
                    $(".layui-layer").each(function () {
                        index = Math.max(index, parseInt($(this).attr("times")));
                    });
                    if (index) {
                        Layer.close(index);
                    }
                }
            }
        });
    }
};
//将语言方法暴露到全局中去
window.__ = Fast.lang;
//将Fast渲染至全局
window.Fast = Fast;

//默认初始化执行的代码
Fast.init();